package com.rtf.framework.web.http;

import com.google.common.collect.Maps;
import com.google.common.primitives.Ints;
import com.rtf.framework.common.config.AppProperties;
import com.rtf.framework.common.exception.AppException;
import com.rtf.framework.common.support.dao.entity.AppJpaBaseEntity;
import com.rtf.framework.common.support.dao.entity.AppJpaIdEntity;
import com.rtf.framework.common.util.UtilAppProperties;
import com.rtf.framework.common.util.UtilMap;
import org.springframework.data.domain.Page;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;

import java.util.HashMap;
import java.util.Map;

/**
 * 请求响应参数格式化
 * @Author : liupeng
 * @Date : 2018/7/27 14:36
 * @Modified By
 */
public class ResponseParam extends HashMap<String, Object> {
	
	private static final long serialVersionUID = 1L;

	private static AppProperties.ResponseConfig responseConfig ;

	private static AppProperties.PageConfig pageConfig ;

	public ResponseParam(){
	}

	/**
	 * 构建ResponseParam全局属性信息
	 * @param appProperties
	 * @return
	 */
	public static ResponseParam appProperties( AppProperties appProperties ){
		ResponseParam responseParam = new ResponseParam() ;
		responseParam.responseConfig = appProperties.getResponseConfig() ;
		responseParam.pageConfig = appProperties.getPageConfig() ;

		return responseParam ;
	}

	/**
	 * 根据flag返回不同类型的结果信息
	 * @param flag
	 * @return
	 */
	public static ResponseParam info(boolean flag){
		if(flag){
			return success() ;
		}
		return fail() ;
	}

	public static ResponseParam success(){
		return success(true) ;
	}

	public static ResponseParam fail(){
		return success(false) ;
	}

	/**
	 * 设置返回的成功状态
	 * @param flag
	 * @return
     */
	public static ResponseParam success(boolean flag){
		ResponseParam successParam = new ResponseParam() ;
		successParam.put(responseConfig.getSuccessParamValue(), flag) ;
		return successParam ;
	}
	
	public static ResponseParam updateSuccess(){
		ResponseParam successParam = success() ;
		successParam.message("更新成功") ;
		return successParam ;
	}
	
	public static ResponseParam updateFail(){
		ResponseParam failParam = fail() ;
		failParam.message("更新失败") ;
		return failParam ;
	}
	
	public static ResponseParam saveSuccess(){
		ResponseParam successParam = success() ;
		successParam.message("添加成功") ;
		return successParam ;
	}
	
	public static ResponseParam saveFail(){
		ResponseParam failParam = fail() ;
		failParam.message("添加失败") ;
		return failParam ;
	}
	
	public static ResponseParam deleteSuccess(){
		ResponseParam successParam = success() ;
		successParam.message("删除成功") ;
		return successParam ;
	}
	
	public static ResponseParam deleteFail(){
		ResponseParam failParam = fail() ;
		failParam.message("删除失败") ;
		return failParam ;
	}

	/**
	 * 是否支持jsonp
	 * @return
	 */
	public boolean isSupportJSONP(){
		return responseConfig.isSupportJsonp() ;
	}

	/**
	 * 代码或标识码
	 * @param code
	 * @return
     */
	public ResponseParam code(Object code){
		this.put(responseConfig.getCodeParam() , code) ;
		return this ;
	}
	
	/**
	 * 添加参数信息，key为message，多次调用addMessage方法会替换相应的key值
	 * @param value
	 * @return
	 */
	public ResponseParam message(Object value){
		this.put(responseConfig.getMessageParam(), value) ;
		return this ;
	}

	/**
	 * 添加单个参数信息，key为data，多次调用addMessage方法会替换相应的key值
	 * @param value
	 * @return
	 */
	public ResponseParam data(Object value){
		if( value == null ){
			return this ;
		}
		if( responseConfig.isEnableExposeDatalist() || !(value instanceof Map) ){
//			if( !value.getClass().isInstance(AppJpaIdEntity.class) )
//			if( AppJpaIdEntity.class.isAssignableFrom( value.getClass() ) ){
//			}
//			throw new AppException("返回参数必须为Map类型 或 实体对象") ;
			this.put(responseConfig.getDataParam(), UtilMap.instanceToMap( value )) ;
		}else{
			this.put(responseConfig.getDataParam(), value) ;
		}

		return this ;
	}

	public static void main(String[] args) {
		AppJpaBaseEntity baseEntity = new AppJpaBaseEntity() ;

		System.out.println( AppJpaIdEntity.class.isAssignableFrom( baseEntity.getClass() ) );
	}

	/**
	 * 添加单个参数信息，key为data，多次调用addMessage方法会替换相应的key值
	 * @param value
	 * @return
	 */
	public ResponseParam data(String key , Object value){

		Object dataObject = this.get( responseConfig.getDataParam() ) ;
		if( dataObject == null ){
			dataObject = Maps.newHashMap() ;
			this.put(responseConfig.getDataParam(), dataObject) ;
		}

		if( !(dataObject instanceof Map) ){
			throw new AppException("使用key-value的方式插入数据，已保存的data对象必须为Map<String,?>") ;
		}

		((Map<String,Object>) dataObject).put( key , value ) ;

		return this ;
	}

	/**
	 * 添加单个参数列表信息，key为data，多次调用addMessage方法会替换相应的key值
	 * @param value
	 * @return
	 */
	public ResponseParam datalist(Iterable<?> value){

		if( responseConfig.isEnableExposeDatalist() ){
			this.put(responseConfig.getDataListParam(), value) ;
		}else{
			Object dataParam = this.get( responseConfig.getDataParam()) ;
			if( dataParam == null ){
				dataParam = Maps.newHashMap() ;
				this.data( dataParam ) ;
			}
			((Map<String,Object>)dataParam).put( responseConfig.getDataListParam(), value ) ;
		}

		return this ;
	}

	/**
	 * 异常的id
	 * @param exceptionId
	 * @return
	 */
	public ResponseParam exceptionId(Object exceptionId){
		this.put(responseConfig.getExceptionIdParam(), exceptionId) ;
		return this ;
	}

	/**
	 * 仅仅包含分页相关的参数
	 * @param page
	 * @return
	 */
	public ResponseParam pageParam(Page<?> page){
		// 构建分页参数对象
		Map<String,Object> pageParams = Maps.newHashMapWithExpectedSize( 10 ) ;
		// 如果前端
		pageParams.put( pageConfig.getPageNum() ,
				UtilAppProperties.appProperties.getPageConfig().getFrontPageNumStartFromZero() ? page.getNumber() : page.getNumber() + 1 ) ;
		pageParams.put( pageConfig.getPageSize() , page.getSize()) ;
		pageParams.put( pageConfig.getPageRealSize() , page.getNumberOfElements()) ;
		pageParams.put( pageConfig.getTotalElements() , Ints.tryParse(page.getTotalElements()+"")) ;
		pageParams.put( pageConfig.getTotalPages() , page.getTotalPages()) ;

		//设置分页参数信息
		if( responseConfig.isEnableExposeDatalist() ){
			this.putAll( pageParams );
		}else{
			Object dataParam = this.get(responseConfig.getDataParam()) ;
			if( dataParam == null ){
				dataParam = Maps.newHashMap() ;
				this.data( dataParam ) ;
			}
			((Map<String,Object>)dataParam).putAll( pageParams );
		}

		return this ;
	}

	/**
	 * 添加参数信息，如果key和SUCCESS_PARAM或FAIL_PARAM_PARAM相同，则会替换相应的值
	 * @param key
	 * @param value
	 * @return
	 */
	public ResponseParam param(String key , Object value){
		this.put(key, value) ;
		return this ;
	}

	/**
	 * 获取包含状态码的response实体对象，状态码默认为200
	 * @return ResponseEntity实体对象
	 */
	public ResponseEntity<ResponseParam> getResponseEntity(){
		return getResponseEntity(HttpStatus.OK) ;
	}
	/**
	 * 获取包含状态码的response实体对象
	 * @param httpStatus 状态码
	 * @return
	 */
	public ResponseEntity<ResponseParam> getResponseEntity(HttpStatus httpStatus){
		return getResponseEntity(httpStatus , null) ;
	}
	
	/**
	 * 获取包含状态码和内容类型的response实体对象
	 * @param httpStatus
	 * @param contentType
	 * @return
	 */
	public ResponseEntity<ResponseParam> getResponseEntity(HttpStatus httpStatus , MediaType contentType){
		if(httpStatus==null){
			httpStatus = HttpStatus.OK ;
		}
		if(contentType==null){
			contentType = MediaType.APPLICATION_JSON ;
		}
		return ResponseEntity.status(httpStatus).contentType(contentType).body(this) ;
	}

}
